#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <jsoncpp/json/json.h>
#include <memory>

#define SELFDEFINE 1//条件编译

namespace protocol_ns
{
    const std::string ProtSep = " ";
    const std::string SEP = "\r\n";

    //len"\r\n"{报文}"\r\n"
    //编码
    std::string Encode(const std::string& json_str)
    {
        int json_str_len = json_str.size();
        std::string proto_str = std::to_string(json_str_len);
        proto_str += SEP;
        proto_str += json_str;
        proto_str += SEP;
        return proto_str;
    }
    
    //判断传过来的报文的长度
    //解码（把原有的json_str解释出来）
    std::string Decode(std::string& inbuffer)
    {
        auto pos = inbuffer.find(SEP);
        if(pos==std::string::npos)
        {
            //返回空串
            return std::string();
        }
        //说明可以找到SEP分隔符
        std::string len_str = inbuffer.substr(0,pos);
        if(len_str.empty())
        {
            return std::string();
        }
        int total_len = len_str.size() + std::stoi(len_str) + 2*SEP.size();
        if(total_len<inbuffer.size())
        {
            return std::string();
        }
        std::string proto_str = inbuffer.substr(pos+SEP.size(),std::stoi(len_str));
        //把inbuffer里面的值清除了
        inbuffer.erase(0,inbuffer.size());
        return proto_str;
    }

    class Request
    {
    public:
        Request()
        {
        }
        Request(int x, int y, char oper) : _x(x), _y(y), _oper(oper)
        {
        }
        bool Serialize(std::string *out)
        {
#ifdef SELFDEFINE
            *out += std::to_string(_x) + ProtSep + _oper + ProtSep + std::to_string(_y);
#else
            // 转换成为字符串
            Json::Value root;
            root["x"] = _x;
            root["y"] = _y;
            root["oper"] = _oper;

            Json::FastWriter writer;
            // Json::StyledWriter writer;
            *out = writer.write(root);
            return true;
#endif
        }
        bool Deserialize(const std::string &in) // 你怎么知道你读到的in 就是完整的一个请求呢？
        {
#ifdef SELFDEFINE
            auto left = in.find(ProtSep);
            if(left==std::string::npos)
                return false;
            auto right = in.rfind(ProtSep);
            if(right==std::string::npos)
                return false;
            
            _x = std::stoi(in.substr(0,left));
            _y = std::stoi(in.substr(right+ProtSep.size()));
            std::string oper = in.substr(left+ProtSep.size(),right-(left+ProtSep.size()));//保证运算符一个单位
            if(oper.size()!=1)
                return false;
            _oper = oper[0];
            return true;

#else
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if (!res)
                return false;

            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
            return true;
#endif
        }

    public:
        int _x;
        int _y;
        char _oper; // "+-*/%" _x _oper _y

    }; // --- "字符串"


     class Response
    {
    public:
        Response()
        {}
        // 有参构造
        Response(int result, int code)
            : _result(result), _code(code)
        {
        }

        // 序列化
        bool Serialize(std::string *out)
        {
#ifdef SELFDEFINE
            *out = std::to_string(_result) + ProtSep +std::to_string(_code);
            return true; 
#else
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;

            Json::FastWriter writer;
            *out = writer.write(root);
            // out为输出型参数

            return true;
#endif
        }

        // 反序列化
        bool DelSerialize(const std::string &in)
        {
#ifdef SELFDEFINE
            auto pos = in.find(ProtSep);
            if(pos==std::string::npos)
                return false;
            _result = std::stoi(in.substr(0,pos));
            _code = std::stoi(in.substr(pos+ProtSep.size()));
            return true;
#else
            Json::Value root;
            Json::Reader reader;

            bool ret = reader.parse(in, root);
            if (!ret)
            {
                return false;
            }

            _result = root["result"].asInt();
            _code = root["code"].asInt();

            return true;
#endif
        }

    public:
        int _result;
        int _code; // 0-->success,1-->除零错误,2,3,4-->非法
    };

    // 随机生产x,y,oper
    class Factory
    {
    public:
        Factory()
        {
            srand(time(nullptr) ^ getpid());
            _oper = "+-*/%&|^";
        }
        std::shared_ptr<Request> BuildRequest()//返 回一个shared智能指针
        {
            int x = rand()%10;
            int y = rand()%5;
            char oper = _oper[rand()%_oper.size()];
            std::shared_ptr<Request> req = std::make_shared<Request>(x,y,oper);
            return req;
        }
        std::shared_ptr<Response> BuildResponse()
        {
            return std::make_shared<Response>();
        }


    private:
        std::string _oper;
    };



}